﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using Accord.Vision.Detection;

namespace Face_Recognition.Haar
{
    public class Stage
    { 
        public int ParentIndex { get; set; }

        [XmlElement("next")]
        public int NextIndex { get; set; }

        public int Width { get;  set; }

        public double Threshold { get; set; }

        public int Height { get; protected set; }

        public TreeNode[][] Trees { get; set; }

        public void setTrees(HaarFeatureNode[][] hfns)
        {
            Trees = new TreeNode[hfns.GetLength(0)][];

            for (int i = 0; i < hfns.GetLength(1); i++)
            {
                for (int j = 0; j < hfns.GetLength(0); j++)
                {
                    Trees[i][j].LeftNodeIndex = hfns[i][j].LeftNodeIndex;
                    Trees[i][j].LeftValue = hfns[i][j].LeftValue;
                    Trees[i][j].RightNodeIndex = hfns[i][j].RightNodeIndex;
                    Trees[i][j].Threshold = hfns[i][j].Threshold;
                    Trees[i][j].RightValue = hfns[i][j].RightValue;

                    Trees[i][j].Feature.Rectangles = new Rectangle[hfns[i][j].Feature.Rectangles.Length];

                    for (int k = 0; k < hfns[i][j].Feature.Rectangles.Length; k++)
                    {
                        Trees[i][j].Feature.Rectangles[k].X = hfns[i][j].Feature.Rectangles[k].X;
                        Trees[i][j].Feature.Rectangles[k].Y = hfns[i][j].Feature.Rectangles[k].Y;
                        Trees[i][j].Feature.Rectangles[k].Width = hfns[i][j].Feature.Rectangles[k].Width;
                        Trees[i][j].Feature.Rectangles[k].Weight = hfns[i][j].Feature.Rectangles[k].Weight;
                        Trees[i][j].Feature.Rectangles[k].ScaledX = hfns[i][j].Feature.Rectangles[k].ScaledX;
                        Trees[i][j].Feature.Rectangles[k].ScaledY = hfns[i][j].Feature.Rectangles[k].ScaledY;

                       // Trees[i][j].Feature.Rectangles[k].Area = hfns[i][j].Feature.Rectangles[k].Area;

                    }
                }
            }
        }

        public Stage()
        {

        }

        public Stage(double threshold)
        {
            this.Threshold = threshold;
        }

        public Stage(double threshold, int parentIndex, int nextIndex)
        {
            this.Threshold = threshold;
            this.ParentIndex = parentIndex;
            this.NextIndex = nextIndex;
        }

        public bool Classify(IntegralImage image, int x, int y, double factor)
        {
            double value = 0;

            foreach (TreeNode[] tree in Trees)
            {
                int current = 0;

                do
                {                 
                    TreeNode node = tree[current];

                    double sum = node.Feature.GetSum(image, x, y);

                    if (sum < node.Threshold * factor)
                    {
                        value += node.LeftValue;
                        current = node.LeftNodeIndex;
                    }
                    else
                    {
                        value += node.RightValue;
                        current = node.RightNodeIndex;
                    }

                } while (current > 0);

                if (value > this.Threshold) return true;
            }

            if (value < this.Threshold)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        //public object Clone()
        //{
        //    TreeNode[][] newTrees = new TreeNode[Trees.Length][];

        //    for (int i = 0; i < newTrees.Length; i++)
        //    {
        //        TreeNode[] tree = Trees[i];
        //        TreeNode[] newTree = newTrees[i] =
        //            new TreeNode[tree.Length];

        //        for (int j = 0; j < newTree.Length; j++)
        //            newTree[j] = (TreeNode)tree[j].Clone();
        //    }

        //    Stage r = new Stage();
        //    r.NextIndex = NextIndex;
        //    r.ParentIndex = ParentIndex;
        //    r.Threshold = Threshold;
        //    r.Trees = newTrees;

        //    return r;
        //}
    }
}
